package tianrun.ziguan.api.calculate.config.service.asset.group.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import org.springframework.transaction.annotation.Transactional;
import tianrun.ziguan.api.calculate.config.dto.request.AssetGroupTreeSaveBody;
import tianrun.ziguan.api.calculate.config.dto.request.common.DeleteBody;
import tianrun.ziguan.api.calculate.config.dto.response.AssetGroupTree;
import tianrun.ziguan.api.calculate.config.entity.TAssetGroup;
import tianrun.ziguan.api.calculate.config.dao.TAssetGroupMapper;
import tianrun.ziguan.api.calculate.config.entity.TCalAsset;
import tianrun.ziguan.api.calculate.config.listener.RefreshCacheListener;
import tianrun.ziguan.api.calculate.config.service.asset.group.ITAssetGroupService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import tianrun.ziguan.api.calculate.config.service.cal.asset.ITCalAssetService;
import tianrun.ziguan.api.calculate.config.service.common.CommonService;
import tianrun.ziguan.api.calculate.config.service.sync.SyncService;
import tianrun.ziguan.api.calculate.config.utils.CollectionUtil;
import tianrun.ziguan.api.calculate.config.utils.StringUtil;
import tianrun.ziguan.api.common.util.ListUtil;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhaoqi
 */
@Service
public class TAssetGroupServiceImpl extends ServiceImpl<TAssetGroupMapper, TAssetGroup> implements ITAssetGroupService {

    private final ITCalAssetService calAssetService;
    private final CommonService commonService;
    private final SyncService syncService;


    public TAssetGroupServiceImpl(ITCalAssetService calAssetService, CommonService commonService, SyncService syncService) {
        this.calAssetService = calAssetService;
        this.commonService = commonService;
        this.syncService = syncService;
    }

    @Override
    public AssetGroupTree listByTree(Long groupId) {
        List<TCalAsset> list = calAssetService.list(Wrappers.<TCalAsset>lambdaQuery().eq(TCalAsset::getAssetGroupId, groupId));
        if (list.isEmpty())return null;
        AssetGroupTree root = list.stream()
                .filter(asset -> StringUtil.isNullOrBlank(asset.getParentAssetNum()))
                .map(AssetGroupTree::of)
                .findFirst().orElseThrow(() -> new IllegalArgumentException("结构异常，未找到资产组根节点"));

        root.setChildren(buildChildren(list,root.getAssetNum()));
        return root;
    }
    private List<AssetGroupTree> buildChildren(List<TCalAsset> list,String myAssetNum){
        if (StringUtil.isEmpty(myAssetNum))return Collections.emptyList();
        return list.stream()
                .filter(asset -> Objects.equals(asset.getParentAssetNum(), myAssetNum))
                .map(AssetGroupTree::of)
                .peek(assetGroupTree -> assetGroupTree.setChildren(buildChildren(list,assetGroupTree.getAssetNum())))
                .collect(Collectors.toList());
    }

    @Transactional
    @Override
    public AssetGroupTree saveByTree(AssetGroupTreeSaveBody body) {
        Long groupId = body.getGroupId();
        AssetGroupTree tree = body.getTree();
        TCalAsset root = tree.to();
        root.setParentAssetNum("");
        root.setAssetGroupId(groupId);
        List<TCalAsset> assets = buildTCalAsset(tree, tree.getAssetNum(),groupId);
        assets.add(root);
        List<TCalAsset> adds = assets.stream().filter(asset -> Objects.isNull(asset.getId())).collect(Collectors.toList());
        HashSet<String> duplicates  = new HashSet<>();
        List<String> assetNums = assets.stream().map(TCalAsset::getAssetNum).collect(Collectors.toList());
        List<String> collect = assetNums.stream().filter(s -> !duplicates.add(s)).collect(Collectors.toList());
        if (!collect.isEmpty())throw new IllegalArgumentException(collect+"资产编号已重复,无法保存,请检查");
        calAssetService.saveOrUpdateBatchByGroup(assets);

        syncService.doSync(adds);

        //delete start
        LambdaQueryWrapper<TCalAsset> queryWrapper = Wrappers.<TCalAsset>lambdaQuery().eq(TCalAsset::getAssetGroupId, groupId).notIn(TCalAsset::getId, assets.stream().map(TCalAsset::getId).collect(Collectors.toList()));
        List<TCalAsset> list = calAssetService.list(queryWrapper);
        //级联删除
        commonService.delete(DeleteBody.of(list.stream().map(TCalAsset::getId).collect(Collectors.toSet()),"t_cal_asset"));
        //delete end
        TAssetGroup assetGroup = getById(groupId);
        RefreshCacheListener.flushByDeptNum(assetGroup.getName());
        return listByTree(groupId);
    }

    private List<TCalAsset> buildTCalAsset(AssetGroupTree tree, String myAssetNum, Long groupId){
        ArrayList<TCalAsset> assets = Lists.newArrayList();
        List<AssetGroupTree> children = tree.getChildren();
        if (ListUtil.isEmpty(children))return assets;
        List<TCalAsset> collect = children.stream().map(child -> {
            TCalAsset asset = child.to();
            asset.setParentAssetNum(myAssetNum);
            asset.setAssetGroupId(groupId);
            return asset;
        }).collect(Collectors.toList());
        assets.addAll(collect);
        children.forEach(child->{
            assets.addAll(buildTCalAsset(child,child.getAssetNum(), groupId));
        });
        return assets;
    }

    @Override
    public List<TAssetGroup> getByIds(Collection<Long> groupIds) {
        if (CollectionUtil.isEmpty(groupIds))return Lists.newArrayList();
        return list(Wrappers.<TAssetGroup>lambdaQuery().in(TAssetGroup::getId,groupIds));
    }

    @Override
    public TAssetGroup getByName(String name) {
        return lambdaQuery().in(TAssetGroup::getName,name).last("limit 1").one();
    }
}
